package com.suredy.app.project.ctrl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.suredy.app.project.constants.ContractLevel;
import com.suredy.app.project.constants.DicKey;
import com.suredy.app.project.constants.ProjectStatus;
import com.suredy.app.project.model.Contract;
import com.suredy.app.project.model.ContractMember;
import com.suredy.app.project.model.ContractPayment;
import com.suredy.app.project.model.Project;
import com.suredy.app.project.model.ProjectCost;
import com.suredy.app.project.model.ProjectMember;
import com.suredy.app.project.service.ProjectMemberSrv;
import com.suredy.app.project.service.ProjectSrv;
import com.suredy.core.ctrl.BaseCtrl;
import com.suredy.core.service.DictionarySrv;
import com.suredy.security.entity.UnitEntity;
import com.suredy.security.entity.User2RoleEntity;
import com.suredy.security.entity.UserEntity;
import com.suredy.security.model.Role;
import com.suredy.security.model.User;
import com.suredy.security.service.RoleSrv;
import com.suredy.security.service.UnitSrv;
import com.suredy.security.service.User2RoleSrv;

/**
 * 项目列表控制器
 * 
 * @author VIVID.G
 * @since 2015-7-30
 * @version v0.1
 */
@Controller
@RequestMapping("/project/form")
public class ProjectFormCtrl extends BaseCtrl {

	private final static Logger log = LoggerFactory.getLogger(ProjectFormCtrl.class);

	@Autowired
	private ProjectSrv projectSrv;

	@Autowired
	private ProjectMemberSrv projectMemberSrv;

	@Autowired
	private UnitSrv unitSrv;

	@Autowired
	private DictionarySrv dictionarySrv;

	@Autowired
	private RoleSrv roleSrv;

	@Autowired
	private User2RoleSrv user2RoleSrv;

	@Value("${role.proj_manager}")
	private String roleCodeOfProjManager;

	@RequestMapping(method = RequestMethod.GET)
	public String form(String id, Model model) {
		String view = "app/project/form";

		Project data = null;

		if (!StringUtils.isBlank(id))
			data = this.projectSrv.get(id);

		if (data == null) {
			view = "app/project/new-form";
			data = this.newProject();
		}

		model.addAttribute("type", this.projType());
		model.addAttribute("status", this.projStatus());
		model.addAttribute("obtain", this.projObtain());
		model.addAttribute("manager", this.projManager());
		model.addAttribute("unit", this.unitSrv.getAll());
		model.addAttribute("customerCompany", this.projCustomerCompany());
		model.addAttribute("supplierCompany", this.projSupplierCompany());
		model.addAttribute("data", data);

		return view;
	}

	@RequestMapping(value = "/new", method = RequestMethod.POST)
	@ResponseBody
	public Object newProject(Project project, Model model) {
		if (project == null)
			return false;

		project.setStatus(ProjectStatus.NOT_START);
		project.setContracted(false);

		// 主管部门
		project.setManageDep(new UnitEntity());
		project.getManageDep().setId(this.getUser().getUnitId());

		project.setInvoiced(false);
		project.setCreateTime(new Date());

		// 项目经理
		project.setMembers(new ArrayList<ProjectMember>());
		project.getMembers().add(this.createManager(project));

		// 主合同
		project.setContracts(new ArrayList<Contract>());
		project.getContracts().add(this.createMainContract(project));

		if (project.getManageDep() != null && StringUtils.isBlank(project.getManageDep().getId()))
			project.setManageDep(null);

		project = this.projectSrv.save(project);

		if (project == null || StringUtils.isBlank(project.getId()))
			return false;

		return project.getId();
	}

	@RequestMapping(value = "/edit-field", method = RequestMethod.POST)
	@ResponseBody
	public boolean editField(String id, String field, String data, String format) {
		if (StringUtils.isBlank(id) || StringUtils.isBlank(field))
			return false;

		try {
			Object val = this.stringToFieldValue(Project.class, field, data, format);

			Map<String, Object> fields = new HashMap<String, Object>();

			fields.put(field.split("\\.")[0], val);

			return this.projectSrv.updateFields(fields, "T.id=?", id) == 1;
		} catch (Exception e) {
			log.error("Edit field error.", e);
		}

		return false;
	}

	@RequestMapping(value = "/edit-manager", method = RequestMethod.POST)
	@ResponseBody
	public boolean editManager(String id, String data) {
		try {
			Map<String, Object> fields = new HashMap<String, Object>();

			UserEntity manager = new UserEntity();
			manager.setId(data);
			fields.put("user", manager);

			return projectMemberSrv.updateFields(fields, "T.project.id=? AND manager=?", id, true) == 1;
		} catch (Exception e) {
			log.error("Edit field error.", e);
		}

		return false;
	}

	@RequestMapping(value = "/edit-members", method = RequestMethod.POST)
	@ResponseBody
	public boolean editMembers(String projId, String[] userIds) {
		return this.projectMemberSrv.updateProjectMembersWithoutManager(projId, userIds);
	}

	@RequestMapping(value = "/cost-chart/{projId}", method = RequestMethod.POST)
	@ResponseBody
	public Object getCostChartData(@PathVariable String projId) {
		if (StringUtils.isBlank(projId))
			return null;

		Project data = this.projectSrv.get(projId);

		if (data == null || data.getCosts() == null)
			return null;

		// xAxis data
		Map<String, List<Object>> ret = new HashMap<String, List<Object>>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");

		for (ProjectCost c : data.getCosts()) {
			if (c == null)
				continue;

			List<Object> xData = ret.get("xData");
			List<Object> yData = ret.get("yData");

			if (xData == null)
				ret.put("xData", xData = new ArrayList<Object>());
			if (yData == null)
				ret.put("yData", yData = new ArrayList<Object>());

			xData.add(sdf.format(c.getPayTime()));
			yData.add(c.getPay() == null ? 0F : c.getPay());
		}

		return ret.isEmpty() ? null : ret;
	}

	@RequestMapping(value = "/payment-chart/{projId}", method = RequestMethod.POST)
	@ResponseBody
	public Object getPaymentChartData(@PathVariable String projId) {
		if (StringUtils.isBlank(projId))
			return null;

		Project proj = this.projectSrv.get(projId);

		if (proj == null || proj.getCosts() == null)
			return null;

		Contract data = proj.getMainContract();

		if (data == null || data.getPays() == null)
			return null;

		// xAxis data
		Map<String, List<Object>> ret = new HashMap<String, List<Object>>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");

		for (ContractPayment c : data.getPays()) {
			if (c == null)
				continue;

			List<Object> xData = ret.get("xData");
			List<Object> yData = ret.get("yData");

			if (xData == null)
				ret.put("xData", xData = new ArrayList<Object>());
			if (yData == null)
				ret.put("yData", yData = new ArrayList<Object>());

			xData.add(sdf.format(c.getDate()));
			yData.add(c.getAmount() == null ? 0F : c.getAmount());
		}

		return ret.isEmpty() ? null : ret;
	}

	private Project newProject() {
		Project data = new Project();

		data.setStatus(ProjectStatus.NOT_START);
		data.setContracted(false);
		data.setInvoiced(false);
		data.setCreateTime(new Date());

		return data;
	}

	private List<String> projType() {
		return this.dictionarySrv.getVals(DicKey.PROJ_TYPE);
	}

	private ProjectStatus[] projStatus() {
		return ProjectStatus.values();
	}

	private List<String> projObtain() {
		return this.dictionarySrv.getVals(DicKey.PROJ_OBTAIN);
	}

	private List<String> projCustomerCompany() {
		return this.dictionarySrv.getVals(DicKey.CUSTOMER_COMPANY);
	}

	private List<String> projSupplierCompany() {
		return this.dictionarySrv.getVals(DicKey.SUPPLIER_COMPANY);
	}

	private List<User> projManager() {
		if (StringUtils.isBlank(this.roleCodeOfProjManager))
			return null;

		if (StringUtils.isBlank(this.getUser().getOrgUniqueCode()))
			return null;

		String roleCode = "G=" + this.roleCodeOfProjManager + "/" + this.getUser().getOrgUniqueCode();

		Role role = this.roleSrv.getByCode(roleCode);

		if (role == null || StringUtils.isBlank(role.getId()))
			return null;

		List<User2RoleEntity> data = this.user2RoleSrv.getByRole(role.getId());

		if (data == null || data.isEmpty())
			return null;

		List<User> ret = new ArrayList<User>();

		for (User2RoleEntity entity : data) {
			if (entity.getUser() != null)
				ret.add(entity.getUser().toVO());
		}

		return ret.isEmpty() ? null : ret;
	}

	/**
	 * 创建项目经理
	 * 
	 * @return
	 */
	private ProjectMember createManager(Project project) {
		if (project == null)
			return null;

		UserEntity user = new UserEntity();
		user.setId(this.getUser().getId());

		ProjectMember member = new ProjectMember();
		member.setUser(user);
		member.setManager(true);
		member.setProject(project);

		return member;
	}

	/**
	 * 创建主合同
	 * 
	 * @return
	 */
	private Contract createMainContract(Project project) {
		Contract mainContract = new Contract();
		mainContract.setNo(project.getNo());
		mainContract.setType(Contract.TYPE_COLLECTION);
		mainContract.setName(project.getName());
		mainContract.setPrice(0F);
		mainContract.setMainContract(true);
		mainContract.setMembers(new ArrayList<ContractMember>());
		mainContract.setProject(project);

		// 甲方
		ContractMember member = new ContractMember();
		member.setLevel(ContractLevel.LEVEL0);
		member.setCompany(StringUtils.isBlank(project.getCustomerCompany()) ? "-" : project.getCustomerCompany());
		member.setPeople(project.getCustomerPeople());
		member.setPhone(project.getCustomerPhone());
		member.setContract(mainContract);

		mainContract.getMembers().add(member);

		// 乙方
		member = new ContractMember();
		member.setLevel(ContractLevel.LEVEL1);
		member.setCompany(this.getUser().getOrgName());
		member.setPeople(this.getUser().getName());
		member.setPhone(this.getUser().getPhone());
		member.setContract(mainContract);

		mainContract.getMembers().add(member);

		return mainContract;
	}

}
